<?php
// +----------------------------------------------------------------------
// | [ WE ONLY DO WHAT IS NECESSARY ]
// +----------------------------------------------------------------------
// | Author < 931274989@qq.com >
// +----------------------------------------------------------------------
// | Explain 
// +----------------------------------------------------------------------
namespace app\api\service;

use app\lib\exception\OrderException;
use app\lib\exception\UserException;
use app\model\Order as orderModel;
use app\lib\enum\OrderStatusEnum;
use app\model\OrderProduct;
use app\model\UserAddress;
use app\model\Product;
use think\Exception;
use think\Db;

class Order
{
  // 订单商品列表，也就是客户端传递过来的products参数
  protected $oProducts;
  
  // 真实的商品信息（包括库存量）
  protected $products;

  protected $uid;

  public function place($uid,$oProducts)
  {
    // oProducts和products作对比
    // product从数据库查询出来
    $this->oProducts = $oProducts;
    $this->products = $this->getProductsByOrder($oProducts);
    $this->uid = $uid;
    $status = $this->getOrderStatus();
    if (!$status['pass']) {
      $status['order_id'] = -1;
      return $status;
    } 
    // 开始创建订单
    $orderSnap = $this->snapOrder($status);
    $order = $this->createOrder($orderSnap);
    $order['pass'] = true;
    return $order;
  }

  // 生成订单写入数据库
  private function createOrder($snap)
  {
    Db::startTrans();
    try 
    {
      $orderNo = self::makeOrderNo();
      $order = new orderModel();
      $order->user_id = $this->uid;
      $order->order_no = $orderNo;
      $order->total_price = $snap['orderPrice'];
      $order->total_count = $snap['totalCount'];
      $order->snap_img = $snap['snapImg'];
      $order->snap_name = $snap['snapName'];
      $order->snap_address = $snap['snapAddress'];
      $order->snap_items = json_encode($snap['pStatus']);
      $order->save();

      $orderID = $order->id;
      $create_time = $order->create_time;
      foreach ($this->oProducts as &$p) {
        $p['order_id'] = $orderID;
      }
      $orderProduct = new OrderProduct();
      $orderProduct->saveAll($this->oProducts);
      Db::commit();
      return [
        'order_no' => $orderNo,
        'order_id' => $orderID,
        'create_time' => $create_time
      ];
    }
    catch (Exception $ex) 
    {
      Db::rollback();
      throw $ex;
    }
  }

  // 生成订单号
  public static function makeOrderNo()
  {
    $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
    $orderSn =
        $yCode[intval(date('Y')) - 2019] . strtoupper(dechex(date('m'))) . date(
            'd') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf(
            '%02d', rand(0, 99));
    return $orderSn;
  }

  // 生成订单快照
  private function snapOrder($status)
  {
    $snap = [
      'orderPrice' => 0, // 订单价格
      'totalCount' => 0, // 商品总数
      'pStatus' => [], // 订单商品信息
      'snapAddress' => null, 
      'snapName' => '',
      'snapImg' => ''
    ];

    $snap['orderPrice'] = $status['orderPrice'];
    $snap['totalCount'] = $status['totalCount'];
    $snap['pStatus'] = $status['pStatusArray'];
    $snap['snapAddress'] = json_encode($this->getUserAddress());
    $snap['snapName'] = $this->products[0]['name'];
    $snap['snapImg'] = $this->products[0]['main_img_url'];
    if (count($this->products) > 1) {
      $snap['snapName'] .= '等';
    }
    return $snap;
  }

  // 用户地址
  private function getUserAddress()
  {
    $userAddress = UserAddress::where('user_id','=',$this->uid)->find();
    if(!$userAddress) {
      throw new UserException([
        'msg' => '用户收货地址不存在，下单失败',
        'errorCode' => 60001,
      ]);
    }
    return $userAddress->toArray();
  }

  // 通过$orderID查询订单信息
  public function checkOrderStock($orderID)
  {
    $oProducts = OrderProduct::where('order_id','=',$orderID)->select();
    $this->oProducts = $oProducts;
    $this->products = $this->getProductsByOrder($oProducts);
    $status = $this->getOrderStatus();
    return $status;
  }

  // 获取订单库存真实状态
  private function getOrderStatus()
  {
    $status = [
      'pass' => true, // 库存量是否足够
      'orderPrice' => 0, // 价格
      'totalCount' => 0, // 商品总数
      'pStatusArray' => [] // 历史商品详情
    ];
    foreach ($this->oProducts as $oProduct) {
      $pStatus = $this->getProductStatus(
        $oProduct['product_id'],$oProduct['count'],$this->products
      );
      if (!$pStatus['haveStock']) {
        $status['pass'] = false;
      }
      $status['orderPrice'] += $pStatus['totalPrice'];
      $status['totalCount'] += $pStatus['counts'];
      array_push($status['pStatusArray'],$pStatus);
    }
    return $status;
  }

  // 单个商品订单状态
  private function getProductStatus($oPID, $oCount, $products)
  {
    $pIndex = -1;

    // 单个商品信息
    $pStatus = [
      'id' => null,
      'haveStock' => false, // 库存状态
      'counts' => 0, // 数量
      'price' => 0, // 商品单价
      'name' => '', 
      'totalPrice' => 0, // 商品价格
      'main_img_url' => '' 
    ];

    for($i=0; $i<count($products); $i++) {
      if($oPID == $products[$i]['id']) {
        $pIndex = $i;
      }
    }
    if($pIndex == -1) {
      // 客户端传递的product_id有可能根本不存在
      throw new OrderException([
        'msg' => 'id为'.$oPID.'商品不存在，创建订单失败'
      ]);
    }
    else {
      $product = $products[$pIndex];
      $pStatus['id'] = $product['id'];
      $pStatus['name'] = $product['name'];
      $pStatus['counts'] = $oCount;
      $pStatus['price'] = $product['price'];
      $pStatus['main_img_url'] = $product['main_img_url'];
      $pStatus['totalPrice'] = $product['price'] * $oCount;
      if($product['stock'] - $oCount >= 0) {
        $pStatus['haveStock'] = true;
      }
    }
    return $pStatus;
  }

  // 根据订单信息查找真实商品信息
  private function getProductsByOrder($oProducts)
  {
    $oPIDs = [];
    foreach ($oProducts as $item) {
      array_push($oPIDs, $item['product_id']);
    } 
    $products = Product::all($oPIDs)
      ->visible(['id','price','stock','name','main_img_url'])
      ->toArray();
    return $products;
  }

  // $jumpPage条转的小程序页面地址
  public function delivery($orderID, $jumpPage = '')
  {
    $order = orderModel::where('id', '=', $orderID)->find();
    if (!$order) {
      throw new OrderException();
    }
    if ($order->status != OrderStatusEnum::PAID) {
      throw new OrderException([
        'msg' => '还没付款呢，想干嘛？或者你已经更新过订单了，不要再刷了',
        'errorCode' => 80002,
        'code' => 403
      ]);
    }
    $order->status = OrderStatusEnum::DELIVERED;
    $order->save();
    //->update(['status' => OrderStatusEnum::DELIVERED]);
    $message = new DeliveryMessage();
    return $message->sendDeliveryMessage($order, $jumpPage);
  }
  
}
?>